#include "CCssCounter.h"

CCssCounter::CCssCounter()
{
	classtype = CSS;
	language_name = "CSS";

	file_extension.push_back(".css");

	BlockCommentStart.push_back("/*");
	BlockCommentEnd.push_back("*/");

	exec_name_list.push_back("top");
	exec_name_list.push_back("bottom");
	exec_name_list.push_back("left");
	exec_name_list.push_back("right");
	exec_name_list.push_back("height");
	exec_name_list.push_back("height");
	exec_name_list.push_back("width");
	exec_name_list.push_back("font");
	exec_name_list.push_back("font-weight");
	exec_name_list.push_back("line-height");
	exec_name_list.push_back("line-width");
	exec_name_list.push_back("font-size");
	exec_name_list.push_back("font-family");
	exec_name_list.push_back("font");
	exec_name_list.push_back("font-variant");
	exec_name_list.push_back("font-style");
	exec_name_list.push_back("font-size");
	exec_name_list.push_back("font-weight");
	exec_name_list.push_back("font-family");
	exec_name_list.push_back("text");
	exec_name_list.push_back("text-transform");
	exec_name_list.push_back("text-indent");
	exec_name_list.push_back("text-decoration");
	exec_name_list.push_back("text-align");
	exec_name_list.push_back("caption-side");
	exec_name_list.push_back("border");
	exec_name_list.push_back("table-layout");
	exec_name_list.push_back("empty-cells");
	exec_name_list.push_back("border");
	exec_name_list.push_back("border-left");
	exec_name_list.push_back("border-right");
	exec_name_list.push_back("border-top");
	exec_name_list.push_back("border-bottom");
	exec_name_list.push_back("border-left-color");
	exec_name_list.push_back("border-right-color");
	exec_name_list.push_back("border-top-color");
	exec_name_list.push_back("border-bottom-color");
	exec_name_list.push_back("border-left-style");
	exec_name_list.push_back("border-right-style");
	exec_name_list.push_back("border-top-style");
	exec_name_list.push_back("border-bottom-style");
	exec_name_list.push_back("border-left-width");
	exec_name_list.push_back("border-right-width");
	exec_name_list.push_back("border-top-width");
	exec_name_list.push_back("border-bottom-width");
	exec_name_list.push_back("border-width");
	exec_name_list.push_back("border-style");
	exec_name_list.push_back("border-collapse");
	exec_name_list.push_back("border-spacing");
	exec_name_list.push_back("table-layout");
	exec_name_list.push_back("background");
	exec_name_list.push_back("background-image");
	exec_name_list.push_back("background-color");
	exec_name_list.push_back("background-repeat");
	exec_name_list.push_back("background-position");
	exec_name_list.push_back("background-attachment");
	exec_name_list.push_back("word-spacing");
	exec_name_list.push_back("counter-increment");
	exec_name_list.push_back("counter-reset");
	exec_name_list.push_back("voice-family");
	exec_name_list.push_back("margin");
	exec_name_list.push_back("margin-top");
	exec_name_list.push_back("margin-right");
	exec_name_list.push_back("margin-bottom");
	exec_name_list.push_back("margin-left");
	exec_name_list.push_back("content");
	exec_name_list.push_back("padding");
	exec_name_list.push_back("padding-top");
	exec_name_list.push_back("padding-bottom");
	exec_name_list.push_back("padding-right");
	exec_name_list.push_back("padding-left");
	exec_name_list.push_back("position");
	exec_name_list.push_back("direction");
	exec_name_list.push_back("float");
	exec_name_list.push_back("clear");
	exec_name_list.push_back("visibility");
	exec_name_list.push_back("white-space");
	exec_name_list.push_back("counter-reset");
	exec_name_list.push_back("counter-increment");
	exec_name_list.push_back("counter-decrement");
	exec_name_list.push_back("list-style");
	exec_name_list.push_back("empty-cells");
	exec_name_list.push_back("cursor");
	exec_name_list.push_back("outline");
	exec_name_list.push_back("voice-family");
	exec_name_list.push_back("stress");
	exec_name_list.push_back("richness");
	exec_name_list.push_back("cue");
	exec_name_list.push_back("cue-before");
	exec_name_list.push_back("cue-after");
	exec_name_list.push_back("azimuth");
	exec_name_list.push_back("volume");
	exec_name_list.push_back("pause");
	exec_name_list.push_back("pause-after");
	exec_name_list.push_back("play");
	exec_name_list.push_back("play-during");
	exec_name_list.push_back("pitch");
	exec_name_list.push_back("page-break-after");
	exec_name_list.push_back("page-break-before");
	exec_name_list.push_back("pitch-range");
	exec_name_list.push_back("caption-side");
	exec_name_list.push_back("clip");
	exec_name_list.push_back("letter-spacing");
	exec_name_list.push_back("line-height");
	exec_name_list.push_back("list-style-image");
	exec_name_list.push_back("list-style-position");
	exec_name_list.push_back("list-style-type");
	exec_name_list.push_back("list-style");
	exec_name_list.push_back("max-width");
	exec_name_list.push_back("max-height");
	exec_name_list.push_back("min-width");
	exec_name_list.push_back("min-width");
	exec_name_list.push_back("orphans");
	exec_name_list.push_back("outline-color");
	exec_name_list.push_back("outline-style");
	exec_name_list.push_back("outline-width");
	exec_name_list.push_back("outline");
	exec_name_list.push_back("quptes");
	exec_name_list.push_back("speak");
	exec_name_list.push_back("speak-numeral");
	exec_name_list.push_back("speak-punctuation");
	exec_name_list.push_back("speak-header");
	exec_name_list.push_back("unicode-bidi");
	exec_name_list.push_back("vertical-align");
	exec_name_list.push_back("z-index");
	exec_name_list.push_back("speak");
	exec_name_list.push_back("speech-rate");
}

int CCssCounter::CountDirectiveSLOC(filemap* fmap, results* result, filemap* fmapBak)
{
	int cntExec = 0;
	int cntData = 0;
	int phyLine = 0;
	char lastLinesLastChar = ' ';
	for( filemap::iterator iter = fmap->begin(); iter!=fmap->end(); iter++)
	{
//		unsigned int posBeg = 0;
		//Get string from line
		string str = iter->line;

		//Check for empty lines. Don't update physical sloc if empty!
		//if (!isEmpty(str)) {
		if(!CUtil::CheckBlank(str))
		{
			phyLine++;
		} 
		else {	//if empty then no need to do anything
		  continue;
		}

		// Trim string and get its length
		//str = strTrim(str);
		str = CUtil::TrimString(str);
		unsigned int strSize = (unsigned int)str.size();

		unsigned int lastSemicolonPos = 0;
		for (unsigned int j = 0; j<strSize ; j++)
		{
			if (str.at(j) == ';')
			{
				if (j == 0)
				{
					if (lastLinesLastChar == ';' || lastLinesLastChar == '{' || lastLinesLastChar == '}')
					{
						lastSemicolonPos = j + 1;
					} 
					else
					{
						cntExec++;
						lastSemicolonPos = j+1;
					}
					if (j == strSize-1)
					{
						lastLinesLastChar = str.at(strSize-1);
					}
					continue;
				}
				string strBetSemiColons = str.substr(lastSemicolonPos, (j-lastSemicolonPos));
				//if (!isEmpty(strBetSemiColons)) {
				if(!CUtil::CheckBlank(strBetSemiColons))
				{
					cntExec++;
				}
				// set last semicolon position
				lastSemicolonPos = j+1;
			}

			if (str.at(j) =='}')
			{
				cntData++;
				// check for last line before closing brace
				if (!(lastLinesLastChar == ';' || lastLinesLastChar == '{' || lastLinesLastChar == '}'))
				{
					cntExec++;	
				}			
			}
		}
		lastLinesLastChar = str.at(strSize-1);
	}
	result->exec_lines[LOG] = cntExec;
	result->data_lines[LOG] = cntData;
	result->exec_lines[PHY] = phyLine;
	return 1;
}

int CCssCounter::LanguageSpecificProcess(filemap* fmap, results* result, filemap* fmapBak) 
{
	string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
	char	prev_char			= ' ';
	string	strLSLOC			= "";
	string	line				= "";
	int		phys_exec_lines		= 0;
	int		phys_data_lines		= 0;

	// The fmap may not contain any lines (e.g. when the file was not found).
	// If this check is not performed, when the for loop starts on the second
	// line (see +1 below) an exception will occur.  Ideally this exception
	// will be passed up to CCodeCounter::CountSLOC and then be caught in
	// MainObject::ProcessSourceList resulting in the output "Unable to count
	// file".  However this exception causes a program crash in Microsoft
	// Visual Studio 2008.  Note that this check causes the exception not to
	// occur, and therefore the "Unable to count file" message not be be
	// displayed, but the more appropriate "unable to open file" message is
	// displayed with or without this check.  (20090808AS)
	if (fmap->size() == 0)
	{
		return 1;
	}

	// Iterating line-by-line of the file
	for (filemap::iterator iter = fmap->begin() + 1; iter!=fmap->end(); iter++)
	{
		line = iter->line;

		// Checking for a blank line
		if (!CUtil::CheckBlank(line))
		{ 
			// If the current line is not blank

			// LSLOC call for the current line, which is not blank and does not contain non-css keywords
			LSLOC(result, line, strLSLOC, prev_char, phys_exec_lines, phys_data_lines);

			int cnt=0;
			CUtil::CountTally(iter->line, exec_name_list, cnt, 1, exclude, "", "", &exec_name_count, result->duplicate);

			// Update physical SLOC
			result->exec_lines[PHY] += phys_exec_lines;
			phys_exec_lines = 0;

			result->data_lines[PHY] += phys_data_lines;
			phys_data_lines = 0;
		}
	}
	return 1;
}

void CCssCounter::LSLOC(results* result, string line, string &strLSLOC, char &lastLinesLastChar, int &phys_exec_lines, int &phys_data_lines)
{
	size_t index = 0, strSize;
	bool trunc_flag = false;

	// Iterating character-by-character for the current line
	while (index < line.length())
	{
		// Trim the current strLSLOC to remove any space characters at the end of the string
		strLSLOC = CUtil::TrimString(strLSLOC);

		// Checking current character
		switch (line[index])
		{
		case ';': case '{':
			// Adding the current strLSLOC to results
			result->addSLOC(strLSLOC, trunc_flag);

			// Reinitialize strLSLOC to null
			strLSLOC = "";

			// If ';' or '{' is found in the first position in the line 
			if (index == 0)
			{
				if (!(lastLinesLastChar == ';' || lastLinesLastChar == '{' || lastLinesLastChar == '}'))
				{
					// Increment physical exec lines
					phys_exec_lines++;
				}
			}

			// If the current strLSLOC is not blank
			if(!CUtil::CheckBlank(strLSLOC))
			{ 
				phys_exec_lines++;
			}
			break;

		case '}':
			phys_data_lines++;

			// If last line's last character is not ';' or '{' or '}'
			if (!(lastLinesLastChar == ';' || lastLinesLastChar == '{' || lastLinesLastChar == '}'))
			{
				phys_exec_lines++;

				// Adding the current strLSLOC to results
				result->addSLOC(strLSLOC, trunc_flag);

				// Reinitialize strLSLOC to null
				strLSLOC = "";
			}			
			break;

		default:	
			// By default for other characters than '{' or ';' or '}' this case is executed
			// Append character to strLSLOC
			strSize = CUtil::TruncateLine(1, strLSLOC.length(), result->lsloc_truncate, trunc_flag);
			if (strSize > 0)
				strLSLOC += line[index];
			break;
		}
		// Incrementing index to point to next character
		index++;
	}
	// Extract the last line's last character
	lastLinesLastChar = line.at(line.length()-1);
}
